home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / smscrl.exe / SMSCROLL.C < prev   
Encoding:
C/C++ Source or Header  |  1992-08-20  |  6.1 KB  |  195 lines

  1. /*
  2.   Simple on-hour no-brainer program to demonstrate how to smoothly scroll a
  3.   4-plane 16 color (EGA, VGA, SVGA up to 800x600) video screen smoothly.
  4.   Moves the image on the screen up/down by n scan lines at a time using the
  5.   hardware latches and string instructions to move 8 pixels at a time as fast
  6.   as the video hardware can manage.
  7.  
  8.   Takes up to 2 cmd-line parameters.
  9.   The first specifies the video mode:
  10.     0     = 320x200 16 color
  11.     1     = 640x200 16 color
  12.     2     = 640x350 16 color
  13.     3     = 640x480 2 color
  14.     other = 640x480 16 color (default).
  15.  
  16.   The second specifies the direction to scroll:
  17.     +     = scroll up
  18.     -     = scroll down
  19.  
  20.   In some video modes or when scrolling down, the last scan line of the
  21.   text used as a demo display will bleed up or down the screen.  The solution
  22.   to this problem in your own programs is to keep about one character line
  23.   worth of data cleared to the background color (at the bottom for scrolling
  24.   up, top for scrolling down).
  25.  
  26.   August 20 1992.
  27.   Joe Slayton - CIS ID 70363,2213
  28.  
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <dos.h>
  34. #include <conio.h>
  35.  
  36. /*-------------------------------------------------------------------------*/
  37.  
  38. void SmoothScroll(unsigned nLines,   unsigned LinesPer,
  39.                   unsigned ScrWidth, unsigned ScrHeight,
  40.                   unsigned ScrollUp)
  41. /*
  42.   Smoothly scrolls the EGA/VGA 16 color screens up or down nLines, moving
  43.   every LinesPer scan lines.  Moves all of the pixels on the screen except
  44.   for the top or bottom nLines on the screen.  This code also works on the
  45.   VGA and MCGA 640x480 2 color mode (this mode is exactly the same as the
  46.   16-color modes but with 3 planes disabled).
  47.   ScrWidth is the width of the screen in pixels (320, 640, 800, etc.);
  48.   ScrHeight is the height of the screen in scan lines (200, 350, 480, etc.).
  49.   ScrollUp tells whether to scroll up or down (0 = down, <> 0 = up).
  50. */
  51. {
  52.  
  53.   unsigned MoveSize;    /* the size of the data block to move */
  54.   unsigned MoveFrom;    /* index of scan line start to move from */
  55.   unsigned MoveTo;      /* index of scan line to move data to */
  56.  
  57.   /* set up video hardware for speedy copying */
  58.   outport(0x03CE, 5); /* mode control register (5) */
  59.   outport(0x03CF, 1); /* r/w mode 00 01 (read 0, write 1) */
  60.  
  61.   /* convert screen width from pixels to bytes */
  62.   ScrWidth >>= 3;
  63.  
  64.   /* figure how much data to move for each scroll */
  65.   MoveSize = ScrWidth * (ScrHeight - nLines);
  66.  
  67.   /* figure starting and stopping addresses */
  68.   if (ScrollUp) {
  69.     MoveFrom = ScrWidth * LinesPer;
  70.     MoveTo   = 0;
  71.   } /* if */
  72.   else {
  73.     MoveFrom = MoveSize + 0;
  74.     MoveTo   = MoveSize + ScrWidth * LinesPer;
  75.   } /* else */
  76.  
  77.   /* while still scan lines left to process */
  78.   do {
  79.  
  80.     /* scroll whole screen block in direction required */
  81.     asm {
  82.  
  83.       push ds           /* save DS for a moment */
  84.       push si           /* save register variables */
  85.       push di
  86.  
  87.       mov  ax, 0xA000   /* both source & dest segs are at screen mem */
  88.       mov  ds, ax       /* set up source pointer */
  89.       mov  si, MoveFrom
  90.       mov  es, ax       /* set up dest pointer */
  91.       mov  di, MoveTo
  92.  
  93.       mov  cx, MoveSize /* # bytes to move */
  94.  
  95.       cld               /* set up for FORWARD move in memory */
  96.  
  97.       cmp  ScrollUp, 0  /* check if scrolling up */
  98.  
  99.       jne  Forward      /* just leave the dir flag the way it was */
  100.  
  101.       std               /* do move BACKWARD through memory */
  102.  
  103.     }
  104.     Forward:
  105.     asm {
  106.  
  107.       rep  movsb        /* do BYTE-ORIENTED move */
  108.  
  109.       cld               /* reset in case anyone expects forward moves */
  110.  
  111.       pop  di           /* restore register variables */
  112.       pop  si
  113.       pop  ds           /* get DS back again */
  114.  
  115.     }
  116.  
  117.     /* one less line to process */
  118.     nLines -= LinesPer;
  119.  
  120.   } while (nLines > 0);
  121.  
  122.   /* reset video hardware to default state */
  123.   outport(0x03CE, 5); /* mode control register (5) */
  124.   outport(0x03CF, 0); /* back to default of 0 */
  125.  
  126. } /* SmoothScroll */
  127.  
  128. /*-------------------------------------------------------------------------*/
  129.  
  130. main(int argc, char *argv[])
  131. {
  132.  
  133.   int I, J;                /* loop counters for character output */
  134.   int Width;               /* width of screen in pixels */
  135.   int Height;              /* height of screen in pixels */
  136.   int ScrollUp = 1;        /* scroll up or down */
  137.   int CharHeight = 16;     /* size of character box */
  138.   struct REGPACK Regs;     /* registers for INT 0x10 operation */
  139.  
  140.   /* check for scrolling up or down */
  141.   if (argc >= 3) {
  142.     ScrollUp = (argv[2][0] == '+') ? 0 : (argv[2][0] == '+') ? 1 : ScrollUp;
  143.   } /* if */
  144.  
  145.   /* select video mode to use based on command-line arg */
  146.   I = -1;
  147.   if (argc >= 2) {
  148.     I = argv[1][0] - '0';
  149.   } /* if */
  150.  
  151.   /* set up correct video mode */
  152.   switch (I) {
  153.     case 0  : Regs.r_ax = 0x000D; /* 320x200 16 color */
  154.               Width = 320; Height = 200; CharHeight =  8; break;
  155.     case 1  : Regs.r_ax = 0x000E; /* 640x200 16 color */
  156.               Width = 640; Height = 200; CharHeight =  8; break;
  157.     case 2  : Regs.r_ax = 0x0010; /* 640x350 16 color */
  158.               Width = 640; Height = 350; CharHeight = 14; break;
  159.     case 3  : Regs.r_ax = 0x0011; /* 640x480 2 color */
  160.               Width = 640; Height = 480; CharHeight = 16; break;
  161.     default : Regs.r_ax = 0x0012; /* 640x480 16 color */
  162.               Width = 640; Height = 480; CharHeight = 16; break;
  163.   } /* switch */
  164.  
  165.   /* turn on graphics mode */
  166.   intr(0x10, &Regs);
  167.  
  168.   /* draw initial 10 lines of text garbage on the screen */
  169.   for (I = 0; I < 80 * 10; I++) {
  170.     fputc(32 + rand() % 26, stdout);
  171.   } /* for */
  172.  
  173.   do {
  174.  
  175.     /* Draw some more text garbage */
  176.     J = rand() % 20;
  177.     for (I = 0; I < J; I++) {
  178.       fputc(32 + rand() % 26, stdout);
  179.     } /* for */
  180.  
  181.     /* scroll up a stock VGA character height, one at a time */
  182.     SmoothScroll(CharHeight, 1, Width, Height, ScrollUp);
  183.  
  184.   /* until user hits a key */
  185.   } while (!kbhit());
  186.  
  187.   /* return to 80x25 color text mode */
  188.   Regs.r_ax = 0x0003;
  189.   intr(0x10, &Regs);
  190.  
  191.   return 0;
  192.  
  193. } /* main */
  194.  
  195.